package com.easycloud.usbPrinter;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.LOG;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


/**
 * This class echoes a string called from JavaScript.
 */
public class usbPrinter extends CordovaPlugin {

    private int socket_port=9100;
    private int socket_status_port=4000;

    private ServerSocket serverSocket;
    private ServerSocket statusSocket;
    private Socket socket_server;
    private Socket socket_status;
    
    private boolean ifListen  =true;
    private boolean ifSocketThreadStart=false;

    private String dataString;

    private String PrinterPath="/dev/usb/";
    private String PrinterLp;
    private String [] permissions = { Manifest.permission.READ_EXTERNAL_STORAGE };
    private static final String LOG_TAG = "usb Printer Log";
    CallbackContext callbackContext;

    /**
     * 转发监听
     */
    private Thread socketThread = new Thread() {
        public void run() {
            while (true) {
                try {
                    if (serverSocket == null && ifListen) {
                        serverSocket = new ServerSocket(socket_port);
//                        serverSocket.setSoTimeout(60*1000);
                    } else if (serverSocket != null) {
                        socket_server = serverSocket.accept();
                        if (socket_server != null) {
                            DataInputStream in = new DataInputStream(new BufferedInputStream(socket_server
                                    .getInputStream()));
                            try {
                                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                                byte[] buffer = new byte[1024];
                                int len = 0;
                                while ((len = in.read(buffer)) != -1) {
                                    outStream.write(buffer, 0, len);
                                }
                                byte[] data = outStream.toByteArray();
                                String lp=GetRootDir(PrinterPath)[0];
                                if(lp != null && fileIsExists(PrinterPath+lp))
                                {
                                    PrinterLp=PrinterPath+lp;
                                    RootCommand("chmod -R 777 "+PrinterLp);
                                    writeFilebyte(PrinterLp,data);
                                }
                                else
                                {
                                    LOG.d(LOG_TAG,"printer is not exist or not root !");
                                }


                            } catch (Exception e) {

                                destoryServerSocket();
                            }
                        }
                    }
                } catch (IOException e1) {

                    destoryServerSocket(); }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {

                }
            }
        }
    };

     /**
     * 状态监听
     */
    private Thread statusThread = new Thread() {
        public void run() {
            while (true) {
                try {
                    if (statusSocket == null && ifListen) {
                        statusSocket = new ServerSocket(socket_status_port);
//                        statusSocket.setSoTimeout(60*1000);
                    } else if (socket_status != null) {
                        socket_status = statusSocket.accept();
                        if (socket_status != null) {
                            DataInputStream in = new DataInputStream(new BufferedInputStream(socket_status.getInputStream()));
                            try {
                                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                                byte[] buffer = new byte[1024];
                                int len = 0;
                                while ((len = in.read(buffer)) != -1) {
                                    outStream.write(buffer, 0, len);
                                }
                                byte[] data = outStream.toByteArray();
                                
                                String lp=GetRootDir(PrinterPath)[0];
                                if(lp != null && fileIsExists(PrinterPath+lp))
                                {
                                    LOG.d(LOG_TAG,"printer is online !");
                                }
                                else
                                {
                                    LOG.d(LOG_TAG,"printer is not exist or not root !");
                                }


                            } catch (Exception e) {

                                destoryStatusSocket();
                            }
                        }
                    }
                } 
                catch (IOException e1) 
                {

                    destoryStatusSocket(); 
                }
                try 
                {
                    Thread.sleep(1);
                } 
                catch (InterruptedException e) 
                {

                }
            }
        }
    };

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        String message;
        this.callbackContext=callbackContext;
        switch (action)
        {
            case "openSocket":
                this.startListen();
                callbackContext.success("true");
                return true;
            case "closeScoket":
                this.stopListen();
                callbackContext.success("true");
                return true;
            case "getLp":
                getLpReq(callbackContext);
                return true;
            case "init":
                this.init();
                callbackContext.success("true");
                return true;
            default:
                return false;

        }

    }

    public void writeFileData(String filename, String content){
        try {
            FileOutputStream fos = new FileOutputStream(filename);//获得FileOutputStream
            //将要写入的字符串转换为byte数组
            byte[]  bytes = content.getBytes();
            fos.write(bytes);//将byte数组写入文件
            fos.close();//关闭文件输出流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void writeFilebyte(String filename, byte[] bytes){
        try {
            FileOutputStream fos = new FileOutputStream(filename);//获得FileOutputStream
            fos.write(bytes);//将byte数组写入文件
            fos.close();//关闭文件输出流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getLpReq(CallbackContext callbackContext)
    {
        if(this.startRequestPermission())
        {
            callbackContext.success(this.getLp());
        }
        else
        {

        }
    }


    public  String getLp()
    {

        if(fileIsExists(this.PrinterPath))
        {
            String[] files=GetRootDir(this.PrinterPath);
            String ret="";
            for (int i=0;i<files.length;i++)
            {
                if(files[i]!=null)
                {
                    ret+= files[i]+"\n";
                }
            }
            return ret;
        }

        return "null";
    }


    /**
     * 开始提交请求权限
     */
    private  boolean startRequestPermission() {
        if(!PermissionHelper.hasPermission(this,permissions[0]))
        {
            PermissionHelper.requestPermission(this,0,permissions[0]);
            return false;
        }
        return true;
    }

    /**
     * processes the result of permission request
     *
     * @param requestCode The code to get request action
     * @param permissions The collection of permissions
     * @param grantResults The result of grant
     */
    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) throws JSONException
    {
        PluginResult result;
        for (int r : grantResults) {
            if (r == PackageManager.PERMISSION_DENIED) {
                result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
                this.callbackContext.sendPluginResult(result);
                return;
            }
        }

        switch(requestCode)
        {
            case 0:
                LOG.d(LOG_TAG,"get 0");
                this.callbackContext.success(this.getLp());
                break;
        }
    }


    public void init() {
        Log.d(LOG_TAG,"plugin init");
        this.startListen();
    }

    private boolean RootCommand(String command)
    {
        Process process = null;
        DataOutputStream os = null;
        try
        {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            LOG.d(LOG_TAG,"Send Command "+command);
            os.writeBytes(command + "\n");
            os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
        } catch (Exception e)
        {
            Log.d("*** DEBUG ***", "ROOT REE" + e.getMessage());
            return false;
        } finally
        {
            try
            {
                if (os != null)
                {
                    os.close();
                }
                process.destroy();
            } catch (Exception e)
            {
            }
        }
        Log.d("*** DEBUG ***", "Root SUC ");
        return true;
    }


    private String[] GetRootDir(String dir)
    {
        Process process = null;
        DataOutputStream os = null;
        DataInputStream is = null;
        DataInputStream es =null;
        String[] outLine=new String[10];
        String line;
        try
        {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            is = new DataInputStream(process.getInputStream());
            es = new DataInputStream(process.getErrorStream());
            LOG.d(LOG_TAG,"dir:"+dir);
            os.writeBytes("ls " + dir + "\n");
            os.flush();
            os.writeBytes("exit\n");
            os.flush();
            LOG.d(LOG_TAG,"flush 1");
            int i=0;
            while ((line = is.readLine()) != null) {
                Log.d("result", line);
                if(i<outLine.length) {

                    outLine[i] = line;
                    i++;
                }

            }
            LOG.d(LOG_TAG,"flush teso");
            process.waitFor();
        } catch (Exception e)
        {
            Log.d("*** DEBUG ***", "ROOT REE" + e.getMessage());
        } finally
        {
            try
            {
                if (os != null)
                {
                    os.close();
                }
                if (is != null)
                {
                    is.close();
                }
                if (es != null)
                {
                    es.close();
                }
                process.destroy();
            } catch (Exception e)
            {
            }
        }
        Log.d("*** DEBUG ***", "Root over ");
        return outLine;
    }


    /**
     * 判断文件是否存在
     * */
    public static boolean fileIsExists(String strFile) {
        try {
            File f = new File(strFile);
            if (!f.exists()) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    private void startListen() {
        ifListen = true;
        if (!ifSocketThreadStart) {
            ifSocketThreadStart = true;
            socketThread.start();
            statusThread.start();
        }


    }

    private void stopListen() {
        ifListen = false;
        destoryServerSocket();
        destoryStatusSocket();
    }

    private void destoryServerSocket() {

        try {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
        } 
        catch (IOException e) {

        } 
        finally 
        {
            serverSocket = null;
        }
        try 
        {
            if (socket_server != null && !socket_server.isClosed()) 
            {
                socket_server.close();
            }
        } 
        catch (IOException e) 
        {

        } 
        finally {
            socket_server = null;
        }
    }

    private void destoryStatusSocket() {

        try {
            if (statusSocket != null && !statusSocket.isClosed()) {
                statusSocket.close();
            }
        } 
        catch (IOException e) {

        } 
        finally 
        {
            statusSocket = null;
        }
        try 
        {
            if (socket_status != null && !socket_status.isClosed()) 
            {
                socket_status.close();
            }
        } 
        catch (IOException e) 
        {

        } 
        finally {
            socket_status = null;
        }
    }


}
